package yxy.cherry.data.actdata;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.reflections.Reflections;
import yxy.apple.logger.Logger;
import yxy.apple.util.FileUtility;
import yxy.apple.util.JSONUtility;
import yxy.apple.util.MD5Utility;
import yxy.apple.util.redisson.RedisException;
import yxy.cherry.data.bean.model.DataClass;
import yxy.cherry.data.input.Version;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class DataHandleAct {

    static private DataHandleAct instance = null;

    public static DataHandleAct getInstance() {
        if (instance == null) {
            instance = new DataHandleAct();
            instance.initDataClass();
        }
        return instance;
    }

    public static void setInstance(DataHandleAct instance) {
        DataHandleAct.instance = instance;
    }

    private Map<String, Class<? extends DataClass>> dataTypeMap = null;

    private Map<String, Class<? extends DataClass>> dataTypeMap1 = null;


    private void initDataClass() {
//      Set<Class<? extends DataClass>> dataTypeSet = ReflectionUtility.getSubTypesOf("yxy.cherry.data.bean", DataClass.class);
    	Reflections reflections = new Reflections("yxy.cherry.data.bean");
    	Set<Class<? extends DataClass>> dataTypeSet = reflections.getSubTypesOf(DataClass.class);
        dataTypeMap = new HashMap<>();
        dataTypeMap1 = new HashMap<>();
        for (Class<? extends DataClass> clazz : dataTypeSet) {
            String name = clazz.getSimpleName();
            if(name.contains("act")){
                dataTypeMap1.put(name,clazz);
            }
            dataTypeMap.put(name, clazz);
        }
    }

//	public static void main(String[] args) {
//		// 本地
//		String redisUrl = "redis://127.0.0.1:6379";
//		String password = "youai";
//		int[] database = { 6, 7, 8 };
//
//	
//		ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
//		try {
//			RedisConnection redisdata = new RedisConnection();
//			redisdata.connect(redisUrl, password, database[2], true, new FastjsonCodec());
//			
//			DataHandleAct module = DataHandleAct.getInstance();
//			module.updateData(redisdata.client(), 1);
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		System.exit(0);
//	}

    public void updateData(RedissonClient client, int areaid) {
        try {
            String murl = System.getProperty("user.dir") + "/data/json/";
            File[] readfiles = FileUtility.getFiles(murl);
           
            UpdateRedisData(client, areaid, readfiles);

        } catch (RedisException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected static Logger logger = Logger.create(DataHandleAct.class);

    public void UpdateRedisData(RedissonClient client, int areaid, File[] readfiles) throws Exception {
        // 获取文件，检查文件：md5校验，键值变化
        Map<String, String> filesMD5 = new HashMap<>();

        ArrayList<File> files = new ArrayList<File>();
        for (File file : readfiles) {
            if (!file.getName().contains("act")) {
                continue;
            }
            files.add(file);
        }

        for (File file : files) {
            String md5 = null;
            try {
                md5 = MD5Utility.getMD5(file);
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("md5解析错误：%s", e.getMessage());
                throw e;
            }
            // 检查内容
            JSONArray dataArray = JSONUtility.readArray(file);
            for (int i = 0; i < dataArray.size(); i++) {
                JSONObject data = dataArray.getJSONObject(i);
                if (!data.containsKey("id")) {
                    logger.error("数据不存在id键值:%s", file.getName());
//					throw new Exception();
                }
            }

            filesMD5.put(file.getName(), md5);
        }

        Version version = Version.defaultVersion;

        // 检查redis库是否有对应的文件md5的key 如果没有属于新建
        RMap<String, String> rmap = client.getMap("ACT:DATA:" + areaid + ":" + version.toString() + ":MD5");

        for (File file : files) {
            String oldmd5 = rmap.get(file.getName());
            String newmd5 = filesMD5.get(file.getName());

            //没有数据 直接添加
            if (oldmd5 == null || oldmd5.equals("")) {
                updateRedisData(client, file, newmd5, areaid, version);
                continue;
            }

            if (newmd5.equals(oldmd5)) {
                continue;
            }

            client.getKeys().deleteByPattern("ACT:DATA:" + areaid + ":" + version.toString() + ":DATAS:" + file.getName());
            updateRedisData(client, file, newmd5, areaid, version);
        }

    }

    private void updateRedisData(RedissonClient client, File file, String newmd5, int areaid, Version version) {
        try {
            client.getMap("ACT:DATA:" + areaid + ":" + version.toString() + ":MD5").put(file.getName(), newmd5);

            HashMap<String, DataClass> dataMap = new HashMap<>();
            String filename = FileUtility.getFileNameWithoutExtension(file);// 文件名
            Class<? extends DataClass> clazz = dataTypeMap.get(filename);
            JSONArray dataArray = JSONUtility.readArray(file);
            for (int i = 0; i < dataArray.size(); i++) {
                DataClass dc = dataArray.getObject(i, clazz);
                dataMap.put(dc.getCode(), dc);
            }
            client.getMap("ACT:DATA:" + areaid + ":" + version.toString() + ":DATAS:" + file.getName()).putAll(dataMap);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public boolean updateRedisData(RedissonClient client, int areaId, String fileName, File file) throws Exception {
        client.getKeys().deleteByPattern("ACT:DATA:" + areaId + ":" + Version.defaultVersion.toString() + ":DATAS:" + fileName);
        String md5 = MD5Utility.getMD5(file);
        HashMap<String, DataClass> dataMap = new HashMap<>();
        JSONArray dataArray = JSONUtility.readArray(file);
        for (int i = 0; i < dataArray.size(); i++) {
            DataClass dc = dataArray.getObject(i, dataTypeMap1.get(fileName));
            dataMap.put(dc.getCode(), dc);
        }
        client.getMap("ACT:DATA:" + areaId + ":" + Version.defaultVersion.toString() + ":DATAS:" + fileName).putAll(dataMap);
        client.getMap("ACT:DATA:" + areaId + ":" + Version.defaultVersion.toString() + ":MD5").put(fileName, md5);
        return true;
    }

    public boolean updateRedisData(RedissonClient client, String fileName, File file) throws Exception {
        client.getKeys().deleteByPattern("ACT:DATA:0:" + Version.defaultVersion.toString() + ":DATAS:" + fileName);
        String md5 = MD5Utility.getMD5(file);
        System.out.println("act:data md5:"+md5);
        HashMap<String, DataClass> dataMap = new HashMap<>();
        JSONArray dataArray = JSONUtility.readArray(file);
        for (int i = 0; i < dataArray.size(); i++) {
            DataClass dc = dataArray.getObject(i, dataTypeMap1.get(fileName));
            dataMap.put(dc.getCode(), dc);
        }
        String filename = fileName+".json";
        client.getMap("ACT:DATA:0:" + Version.defaultVersion.toString() + ":DATAS:" + fileName).putAll(dataMap);
        client.getMap("ACT:DATA:0:" + Version.defaultVersion.toString() + ":MD5").put(filename, md5);
        return true;
    }

    public boolean updateRedisData1(RedissonClient client, String fileName, File file) throws Exception {
        client.getKeys().deleteByPattern("DATA:" + Version.defaultVersion.toString() + ":DATAS:" + fileName);
        String md5 = MD5Utility.getMD5(file);
        System.out.println("data md5:"+md5);
        HashMap<String, DataClass> dataMap = new HashMap<>();
        JSONArray dataArray = JSONUtility.readArray(file);
        for (int i = 0; i < dataArray.size(); i++) {
            DataClass dc = dataArray.getObject(i, dataTypeMap.get(fileName));
            dataMap.put(dc.getCode(), dc);
        }
        String filename = fileName+".json";
        client.getMap("DATA:" + Version.defaultVersion.toString() + ":DATAS:" + fileName).putAll(dataMap);

        client.getMap("DATA:" + Version.defaultVersion.toString() + ":MD5").put(filename, md5);
        return true;
    }


}
